Skip to content

Conversation

martinsaposnic
Copy link
Contributor

@martinsaposnic martinsaposnic commented Jun 9, 2025

The feature

lightningdevkit/ldk-node#479

Currently, our LSPS2 service implementation only supports the lsp_trusts_client model, which means that "If the client does not claim the payment, and the funding transaction confirms, then the LSP will have its funds locked in a channel that was not paid for."

On a client_trusts_lsp model, the LSP will NOT broadcast the funding transaction until the client claims the payment.

The plan:

(This plan was validated and acknowledged by @tnull in private). There are differences between the plan and the implementation, but it roughly describes the approach.

  • LSPS2 Process & Events:
These are handled the same way as before. No changes here.

  • When the OpenChannel event is emitted, ldk-node calls create_channel as usual. The key difference is: If client_trusts_lsp = true, after emitting the OpenChannel event, we start tracking the HTLC that our client will eventually claim.

  • Funding Transaction Broadcast Logic:
The batch_funding_transaction_generated_intern function decides whether the funding transaction should be broadcast automatically. There are two existing funding types:

    • Checked: Validates and auto-broadcasts.
    • Unchecked: Skips validation and requires manual broadcast.

    I will introduce a third type:

    • CheckedManualBroadcast: Validates, but sets manual broadcast.
  • With this:

    • If client_trusts_lsp = false, ldk-node uses funding_transaction_generated (default behavior).
    • If client_trusts_lsp = true, it uses funding_transaction_generated_with_delayed_broadcast, which sets the funding type to CheckedManualBroadcast (validates but sets manual broadcast).
  • lsps2_service on
ldk-node will now interact with lsps2_service on rust-lightning in two new key moments:

    • When it receives the FundingTxBroadcastSafe event, it notifies lsps2_service on rust-lightning, which marks a flag as true.
    • When the client claims the HTLC (::PaymentClaimed), ldk-node notifies lsps2_service on rust-lightning, which marks another flag as true.
    • Once both flags are true, we are ok to proceed to broadcast the funding transaction.

Changes:

  • a new FundingType called CheckedManualBroadcast, which behaves the same as the FundingType::Checked, but it returns false when is_manual_broadcast is called. Essentially, it validates everything (same as the FundingType::Checked) but it does not automatically broadcast (same as FundingType::Unchecked)
  • new public function funding_transaction_generated_manual_broadcast on channel_manager. Uses FundingType::CheckedManualBroadcast, which validates but does not automatically broadcast
  • new public function channel_needs_manual_broadcast. This is used by ldk-node to know if funding_transaction_generated or funding_transaction_generated_manual_broadcast should be called when FundingGenerationReady event is triggered
  • new public function store_funding_transaction. This is used by ldk-node when the funding transaction is created. We need to store it because the broadcast of the funding transaction may be deferred.
  • new public function funding_tx_broadcast_safe. This is used by ldk-node when the FundingTxBroadcastSafe event is triggered
  • a new enum TrustModel is introduced, which depending on the trust model that the user chose, it will have a few properties to track:
    • if the client claimed the htlc,
    • the status of funding_tx_broadcast_safe.
    • hold the funding_tx for later use
  • This new TrustModel enum will be created when the OpenChannel is triggered, and will be saved in the OutboundJITChannelState
  • Every time the TrustModel changes values, the function broadcast_transaction_if_applies is called, so it checks if it's time to broadcast the funding transaction
  • An unsafe_broadcast_transaction function is also introduced on channel_manager, which will be called by broadcast_transaction_if_applies from the lsps2/service

LDK Node integration

In this PR lightningdevkit/ldk-node#572 on ldk-node, you can see that 2 tests are created that demonstrates the funcionality described above.

  • First test:

client_trusts_lsp=true

In the test, receive_via_jit_channel_manual_claim is called, the mempool is checked to assert that the funding transaction was not broadcasted yet (it should not because client_trusts_lsp=true, and the client has not claimed the htlc yet).

Then the client calls claim_for_hash, and the mempool is checked again, and now the funding transaction should be there

  • Second test:

client_trusts_lsp=false

In the test, receive_via_jit_channel_manual_claim is called, the mempool is checked to assert that the funding transaction was broadcasted (because the LSP trusts the client), even though the client has not claimed the htlc yet. In this case, the LSP was tricked, and it will have its funds locked in a channel that was not paid for.

Side note: for the tests to work I had to create a new receive_via_jit_channel_manual_claim so the client can manually claim the htlc using the claim_for_hash.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jun 9, 2025

👋 I see @TheBlueMatt was un-assigned.
If you'd like another reviewer assignment, please click here.

@tnull tnull self-requested a review June 9, 2025 19:17
Copy link

codecov bot commented Jun 9, 2025

Codecov Report

❌ Patch coverage is 86.10169% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.82%. Comparing base (bf87832) to head (f37b129).

Files with missing lines Patch % Lines
lightning-liquidity/src/lsps2/service.rs 84.75% 39 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3838      +/-   ##
==========================================
+ Coverage   88.76%   88.82%   +0.05%     
==========================================
  Files         176      176              
  Lines      129345   129618     +273     
  Branches   129345   129618     +273     
==========================================
+ Hits       114812   115127     +315     
+ Misses      11925    11881      -44     
- Partials     2608     2610       +2     
Flag Coverage Δ
fuzzing 21.94% <3.25%> (-0.07%) ⬇️
tests 88.65% <86.10%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@martinsaposnic martinsaposnic force-pushed the client-trusts-lsp branch 2 times, most recently from 5d8508d to a038ab6 Compare June 9, 2025 19:51
@martinsaposnic
Copy link
Contributor Author

A few extra concerns:

HTLCs routed over 0-conf channels might hit CLTV timeouts if the channel should be confirmed but isn’t yet, so if the user takes forever to claim the payment, then there could be some trouble there.

Also, I'm not sure if it would be better to have new possible states to explicitly model the idea of having sent the channel_ready but the funding_tx is not broadcasted yet. Also sharing the trust_model state between 4 of the 5 possible states is not something I'm convinced. I have a few different options for this, but I'm open to comments and suggestions

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 5th Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 6th Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 7th Reminder

Hey @tnull! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this.

This generally makes sense to me, although we should really work out how we'd deal with operational channels for which we withhold the funding transaction broadcast.

HTLCs routed over 0-conf channels might hit CLTV timeouts if the channel should be > confirmed but isn’t yet, so if the user takes forever to claim the payment, then there
could be some trouble there.

Yes. IMO this means that we need to introduce proper (read: clean API, and tested) support for 'hosted channels', i.e., channels that are operational even though the funding transaction hasn't been confirmed yet. Not sure if @TheBlueMatt has an opinion here?

Also, I'm not sure if it would be better to have new possible states to explicitly model > the idea of having sent the channel_ready but the funding_tx is not broadcasted yet. > Also sharing the trust_model state between 4 of the 5 possible states is not > something I'm convinced. I have a few different options for this, but I'm open to > comments and suggestions

Yeah, as mentioned in the comments, it would def. be preferable if we could avoid the many clones. Also it's overall a lot of boilerplate for just three fields handed through, maybe there is a simpler approach?

@@ -11,6 +11,7 @@

use alloc::string::{String, ToString};
use alloc::vec::Vec;
use bitcoin::Transaction;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Let's move this down to the other bitcoin types.


fn new(client_trusts_lsp: bool) -> Self {
if client_trusts_lsp {
return TrustModel::ClientTrustsLsp {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please avoid these explicit returns here.

if client_trusts_lsp {
return TrustModel::ClientTrustsLsp {
funding_tx_broadcast_safe: false,
htlc_claimed: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe payment_claimed to align with the event type?

let mut payment_queue = core::mem::take(payment_queue);
payment_queue.add_htlc(htlc);
*self = OutboundJITChannelState::PendingChannelOpen {
payment_queue,
opening_fee_msat: *opening_fee_msat,
trust_model: trust_model.clone(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good if we could find a way to avoid these clones. Given that these are just two bools and the transaction option, I also wonder if it's indeed worth all the boilerplate, or if it might suffice to have these fields live on the state/channel objects directly.

Ok(())
}

/// Called by ldk-node when the funding transaction is safe to broadcast.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that in this context we don't know where this will be used, so we shouldn't assume LDK Node is the only consumer of this API.

/// broadcast it manually.
///
/// Used in LSPS2 on a client_trusts_lsp model
CheckedManualBroadcast(Transaction),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Let's move to the second positition here and elsewhere.

/// # Warning
/// Improper use of this method could lead to channel state inconsistencies.
/// Ensure the transaction being broadcast is valid and expected by LDK.
pub fn unsafe_broadcast_transaction(&self, tx: &Transaction) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure if this would qualify for the unsafe_ prefix and the Warning. It's really just the normal flow, just that we leave broadcasting to the user instead of using the BroadcasterInterface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we leave broadcasting to the user instead of using the BroadcasterInterface

actually, I think it would be good to emit an event ClientPaidSoPleaseBroadcastTransactionNow instead of doing it automatically, or even better, reuse the LdkEvent::FundingTxBroadcastSafe, which is literally the event used to let the user know they should manually broadcast a transaction. I will investigate if that's possible

@@ -1075,7 +1075,7 @@ impl PaymentParameters {
}

/// A struct for configuring parameters for routing the payment.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unrelated?

@@ -35,7 +35,7 @@ lightning = { version = "0.2.0", path = "../lightning", default-features = false
lightning-macros = { version = "0.2", path = "../lightning-macros", default-features = false }
bitcoin = { version = "0.32.2", default-features = false }
futures = { version = "0.3", optional = true }
esplora-client = { version = "0.12", default-features = false, optional = true }
esplora-client = { version = "0.11", default-features = false, optional = true }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't include unrelated changes here.

@ldk-reviews-bot
Copy link

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

@tnull
Copy link
Contributor

tnull commented Jul 24, 2025

This needs a rebase now that #3662 landed.

@martinsaposnic martinsaposnic force-pushed the client-trusts-lsp branch 3 times, most recently from 8d7da60 to 82a4bc1 Compare August 12, 2025 18:11
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let me know if/when you deem this ready for review!

@martinsaposnic
Copy link
Contributor Author

Please let me know if/when you deem this ready for review!

I'm close, I have a half baked functional test. I want to finish that before putting this as ready for review

@martinsaposnic martinsaposnic force-pushed the client-trusts-lsp branch 3 times, most recently from fb259f4 to 6412945 Compare August 18, 2025 20:38
@martinsaposnic
Copy link
Contributor Author

ok, this should be ready now @tnull

all comments are addressed in fixup commits.

also I wrote a full end to end test that covers the client_trusts_lsp flow (directly in this repo, not in ldk-node, which was not possible before! 😄 ) . also added some documentation that explains how the client_trusts_lsp flow works.

thanks!

@martinsaposnic martinsaposnic marked this pull request as ready for review August 18, 2025 20:45
@ldk-reviews-bot ldk-reviews-bot requested a review from jkczyz August 18, 2025 20:45
@TheBlueMatt TheBlueMatt removed the request for review from jkczyz August 18, 2025 20:54
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @TheBlueMatt! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically LGTM if we just drop the new broadcast event. Feel free to squash, in any case.

pub fn payment_forwarded(&self, next_channel_id: ChannelId) -> Result<(), APIError> {
/// [`Event::BroadcastFundingTransaction`]: crate::lsps2::event::LSPS2ServiceEvent::BroadcastFundingTransaction
pub fn payment_forwarded(
&self, next_channel_id: ChannelId, skimmed_fee_msat: Option<u64>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO skimmed_fee_msat shouldn't be an Option. That implies to a user that they can skip it. Its only an Option in the corresponding Event for serialization backwards compatibility, but we should push the user to simmed_fee_msat.unwrap_or(0).

///
/// This method should only be used when manual control over transaction
/// broadcast timing is required (e.g. client_trusts_lsp=true)
pub fn broadcast_transaction(&self, tx: &Transaction) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really not sure what the point of this is. We're already holding a reference to the BroadcasterInterface (now), so why are we creating an Event with the sole purpose of making the user call a method back on the code that generated the event? Why can't we just do the broadcast directly and remove the event entirely? And, if we keep the event, what's the point of having a BroadcasterInterface reference is its just used for a public method that proxies it.

@TheBlueMatt TheBlueMatt added this to the 0.2 milestone Aug 30, 2025
@martinsaposnic
Copy link
Contributor Author

thanks for the review @TheBlueMatt !

all fixups are squashed, and also addressed the latest comments in new fixup commits

thanks!!

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixups LGTM, I'll leave it to @tnull to look at this one last time and request remaining fixups be squashed.

Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current code mostly LGTM, some comments.

I still think we need to make sure nothing unexpected happens if we hit HTLC timeouts before the funding transaction is broadcast and confirmed. In particular, we need to make sure that a malicious client can't have incoming channels to LSP get force-closed and that the LSP is able to claim all their funds at any point in the flow.

IIRC, we previously discussed different 'hacky' ways to convince LDK to simply fail back the HTLCs (e.g., 'simulate' confirming the funding transaction and/or any force-close transaction), but the conclusion was that we want/need to create a more easy-to-use/safe interface. (cc @TheBlueMatt)

/// were being held for that JIT channel are forwarded. In a `client_trusts_lsp` flow, once
/// the fee has been fully paid, the channel's funding transaction will be broadcasted.
///
/// Note that `next_channel_id` and `skimmed_fee_msat` are required to be provided. Therefore, the corresponding
/// [`Event::PaymentForwarded`] events need to be generated and serialized by LDK versions
/// greater or equal to 0.0.107.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, 0.0.107 is only the min required version for next_channel_id, skimmed_fee_msat was introduced with 0.0.122 to PaymentForwarded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to rewrite this to say

/// For LDK >= 0.0.107 and < 0.0.122 pass `0` for `skimmed_fee_msat` and only use `client_trusts_lsp = false`

but that won't work since now we are also checking skimmed_fee_msat for lsp_trusts_client flows, and the flow won't progress to OutboundJITChannelState::PaymentForwarded if the fee is not paid

so I guess LDK's minimum version for LSPS2 should be 0.0.122 now so skimmed_fee_msat is always present?

/// Note that `next_channel_id` and `skimmed_fee_msat` are required to be provided. Therefore, the corresponding
/// [`Event::PaymentForwarded`] events need to be generated and serialized by LDK versions
/// greater or equal to 0.0.122.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it will only be possible to upgrade from 0.0.122 and above, which is perfectly fine though.

@@ -1412,11 +1534,139 @@ where
peer_state_lock.is_prunable() == false
});
}

/// Checks if the JIT channel with the given `user_channel_id` needs manual broadcast.
/// Will be true if client_trusts_lsp is set to true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please tick:

Suggested change
/// Will be true if client_trusts_lsp is set to true
///
/// Will be `true` if `client_trusts_lsp` is set to `true`.

}

/// Called to store the funding transaction for a JIT channel.
/// This should be called when the funding transaction is created but before it's broadcast.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"but before it's broadcast" could be a bit more verbose or dropped. Is there any additional responsibility on the user, or can they just call this when they created the funding tx?

// 7. Call the service's channel_ready function
// 8. The service will now forward the intercepted HTLC to the client on the new JIT channel
// 9. The client will see the PaymentClaimable event
// 10. Assert that the service has not broadcasted the funding transaction yet, because the client has not claimed the HTLC yet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test variant that at this point waits for a long time, surpassing the incoming HTLCs timeouts? In particular, can we check that the incoming channel isn't force-closed when the client doesn't claim the payment for a long time (or is offline)?

@martinsaposnic
Copy link
Contributor Author

thank you for the review @tnull

I squashed the old fixups and pushed 2 new fixups that address the latest comments.

thanks!

@martinsaposnic martinsaposnic requested a review from tnull September 2, 2025 19:05
@TheBlueMatt
Copy link
Collaborator

I still think we need to make sure nothing unexpected happens if we hit HTLC timeouts before the funding transaction is broadcast and confirmed. In particular, we need to make sure that a malicious client can't have incoming channels to LSP get force-closed and that the LSP is able to claim all their funds at any point in the flow.

Mmm, this is a good point. If an (outbound) HTLC is set to expire soon LDK will FC the channel and broadcast the commitment tx (which will not be confirm-able, as we never broadcasted the funding transaction). If the downstream logic doesn't do an anchor-output CPFP bump, that's totally fine. LDK will be unable to get the commitment tx confirmed and no problem, at least as long as lightning-liquidity doesn't broadcast the funding transaction after the channel is closed (which seems like a good check to add in this PR!).

If LDK does do a CPFP bump against the channel that doesn't exist that's problematic, but its not clear to me what to do about it - I don't think we want to never broadcast the commitment transaction if the funding is unconfirmed, the commitment tx may end up CPFP'ing the funding transaction in some cases and we want to allow for that (esp with anchors!). I suppose we could track the manual-broadcast flag, pass that through to the ChannelMonitor and have it not broadcast commitment transactions/CPFP-events if that flag is set and the commitment is unconfirmed, though it feels a bit hacky. We could also just document that users should track these channels and not CPFP them but that is also quite possibly gonna be missed and then you end up with a mess.

IIRC, we previously discussed different 'hacky' ways to convince LDK to simply fail back the HTLCs (e.g., 'simulate' confirming the funding transaction and/or any force-close transaction), but the conclusion was that we want/need to create a more easy-to-use/safe interface. (cc @TheBlueMatt)

Hmm, I vaguely recall this discussion being more about the implementation itself, which is handled with the manual-broadcasting methods added here, but I could be wrong.

@tnull tnull removed their request for review September 3, 2025 07:46
@martinsaposnic
Copy link
Contributor Author

had to rebase with main to fix a silent conflict on the lsps2 tests

this was the thing missing:

image

CI should pass now

@martinsaposnic
Copy link
Contributor Author

I still think we need to make sure nothing unexpected happens if we hit HTLC timeouts before the funding transaction is broadcast and confirmed. In particular, we need to make sure that a malicious client can't have incoming channels to LSP get force-closed and that the LSP is able to claim all their funds at any point in the flow.

Mmm, this is a good point. If an (outbound) HTLC is set to expire soon LDK will FC the channel and broadcast the commitment tx (which will not be confirm-able, as we never broadcasted the funding transaction). If the downstream logic doesn't do an anchor-output CPFP bump, that's totally fine. LDK will be unable to get the commitment tx confirmed and no problem, at least as long as lightning-liquidity doesn't broadcast the funding transaction after the channel is closed (which seems like a good check to add in this PR!).

just pushed a new fixup commit (f37b129) that adds some logic and a test that asserts that the funding tx cannot be broadcast after the channel is closed.

If LDK does do a CPFP bump against the channel that doesn't exist that's problematic, but its not clear to me what to do about it - I don't think we want to never broadcast the commitment transaction if the funding is unconfirmed, the commitment tx may end up CPFP'ing the funding transaction in some cases and we want to allow for that (esp with anchors!). I suppose we could track the manual-broadcast flag, pass that through to the ChannelMonitor and have it not broadcast commitment transactions/CPFP-events if that flag is set and the commitment is unconfirmed, though it feels a bit hacky. We could also just document that users should track these channels and not CPFP them but that is also quite possibly gonna be missed and then you end up with a mess.

not sure what to do about this. I can do the "track the manual-broadcast flag and pass it to the ChannelMonitor to not broadcast commitment txs" but not sure if that's what we want.

thoughts? @TheBlueMatt @tnull

@TheBlueMatt
Copy link
Collaborator

IMO that's what we want, but I certainly don't feel strongly. @tnull?

@TheBlueMatt
Copy link
Collaborator

Actually, yea, I do think we should do that. I don't see a reason why that would be problematic as long as we document it carefully on the manual-broadcast method.


if let Some(funding_tx) = funding_tx {
self.tx_broadcaster.broadcast_transactions(&[&funding_tx]);
// Broadcast the funding transaction only if the LDK channel is still usable. In
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, wouldn't checking is_usable be potentially race-y if the client manages to disconnect just after claiming? Would probably make sense to check is_channel_ready?

other => panic!("Expected PaymentClaimable, got {:?}", other),
};

client_node.inner.node.claim_funds(preimage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also advance the (service's) chain state so the HTLC timeout would be hit before the client claims the HTLC, and see what happens?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants